<?php
/**
 * @package Joostina
 * @copyright Авторские права (C) 2008-2010 Joostina team. Все права защищены.
 * @license Лицензия http://www.gnu.org/licenses/gpl-2.0.htm GNU/GPL, или help/license.php
 * Joostina! - свободное программное обеспечение распространяемое по условиям лицензии GNU/GPL
 * Для получения информации о используемых расширениях и замечаний об авторском праве, смотрите файл help/copyright.php.
 */

// запрет прямого доступа
defined('_JLINDEX') or die();
/* vim: set expandtab tabstop=4 shiftwidth=4:*/
// +----------------------------------------------------------------------+
// | PHP version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyrieht (c) 1997-2002 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/3_0.txt.                                  |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | license@php.net so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Authors: Ian Eure <ieure@php.net>                                    |
// +----------------------------------------------------------------------+
//
// $Id:Type.php 13 2007-05-13 07:10:43Z soeren $

require_once dirname(__file__) . "/../PEAR.php";

$_fileCmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd');
$_fileCmd = 'file';

/**
 * Class for working with MIME types
 * @version @version@
 * @package @package@
 * @author Ian Eure <ieure@php.net>
 */
class MIME_Type{
	/**
	 * The MIME media type
	 * @var string
	 */
	var $media = '';

	/**
	 * The MIME media sub-type
	 * @var string
	 */
	var $subType = '';

	/**
	 * Optional MIME parameters
	 * @var array
	 */
	var $parameters = array();

	/**
	 * List of valid media types
	 * @var array
	 */
	var $validMediaTypes = array('text', 'image', 'audio', 'video', 'application',
		'multipart', 'message');


	/**
	 * Constructor.
	 * If $type is set, if will be parsed and the appropriate class vars set. If not,
	 * you get an empty class. This is useful, but not quite as useful as parsing a
	 * type.
	 * @param  string $type MIME type
	 * @return void
	 */
	function MIME_Type($type = false){
		if($type){
			$this->parse($type);
		}
	}


	/**
	 * Parse a mime-type
	 * @param  $type string MIME type to parse
	 * @return void
	 */
	function parse($type){
		$this->media = $this->getMedia($type);
		$this->subType = $this->getSubType($type);
		if(MIME_Type::hasParameters($type)){
			require_once 'MIME/Type/Parameter.php';
			foreach(MIME_Type::getParameters($type) as $param){
				$param = new MIME_Type_Parameter($param);
				$this->parameters[$param->name] = $param;
			}
		}
	}


	/**
	 * Does this type have any parameters?
	 * @param  $type   string MIME type to check
	 * @return boolean true if $type has parameters, false otherwise
	 * @static
	 */
	function hasParameters($type){
		if(strstr($type, ';')){
			return true;
		}
		return false;
	}


	/**
	 * Get a MIME type's parameters
	 * @param  $type string MIME type to get parameters of
	 * @return array $type's parameters
	 * @static
	 */
	function getParameters($type){
		$params = array();
		$tmp = explode(';', $type);
		for($i = 1; $i < count($tmp); $i++){
			$params[] = trim($tmp[$i]);
		}
		return $params;
	}


	/**
	 * Strip paramaters from a MIME type string
	 * @param  string $type MIME type string
	 * @return string MIME type with parameters removed
	 * @static
	 */
	function stripParameters($type){
		if(strstr($type, ';')){
			return substr($type, 0, strpos($type, ';'));
		}
		return $type;
	}


	/**
	 * Get a MIME type's media
	 * @note   'media' refers to the portion before the first slash
	 * @param  $type  string MIME type to get media of
	 * @return string $type's media
	 * @static
	 */
	function getMedia($type){
		$tmp = explode('/', $type);
		return strtolower($tmp[0]);
	}


	/**
	 * Get a MIME type's subtype
	 * @param  $type string MIME type to get subtype of
	 * @return string $type's subtype
	 * @static
	 */
	function getSubType($type){
		$tmp = explode('/', $type);
		$tmp = explode(';', $tmp[1]);
		return strtolower(trim($tmp[0]));
	}


	/**
	 * Create a textual MIME type from object values
	 * This function performs the opposite function of parse().
	 * @return string MIME type string
	 */
	function get(){
		$type = strtolower($this->media . '/' . $this->subType);
		if(count($this->parameters)){
			foreach($this->parameters as $key => $null){
				$type .= '; ' . $this->parameters[$key]->get();
			}
		}
		return $type;
	}


	/**
	 * Is this type experimental?
	 * @note   Experimental types are denoted by a leading 'x-' in the media or
	 *         subtype, e.g. text/x-vcard or x-world/x-vrml.
	 * @param  string $type MIME type to check
	 * @return boolean true if $type is experimental, false otherwise
	 * @static
	 */
	function isExperimental($type){
		if(substr(MIME_Type::getMedia($type), 0, 2) == 'x-' || substr(MIME_Type::getSubType
		($type), 0, 2) == 'x-'
		){
			return true;
		}
		return false;
	}


	/**
	 * Is this a vendor MIME type?
	 * @note   Vendor types are denoted with a leading 'vnd. in the subtype.
	 * @param  string  $type MIME type to check
	 * @return boolean true if $type is a vendor type, false otherwise
	 * @static
	 */
	function isVendor($type){
		if(substr(MIME_Type::getSubType($type), 0, 4) == 'vnd.'){
			return true;
		}
		return false;
	}


	/**
	 * Is this a wildcard type?
	 * @param  string  $type MIME type to check
	 * @return boolean true if $type is a wildcard, false otherwise
	 * @static
	 */
	public static function isWildcard($type){
		if($type == '*/*' || MIME_Type::getSubtype($type) == '*'){
			return true;
		}
		return false;
	}


	/**
	 * Perform a wildcard match on a MIME type
	 * Example:
	 * MIME_Type::wildcardMatch('image/*', 'image/png')
	 * @param  string  $card Wildcard to check against
	 * @param  string  $type MIME type to check
	 * @return boolean true if there was a match, false otherwise
	 */
	public static function wildcardMatch($card, $type){
		if(!MIME_Type::isWildcard($card)){
			return false;
		}

		if($card == '*/*'){
			return true;
		}

		if(MIME_Type::getMedia($card) == MIME_Type::getMedia($type)){
			return true;
		}
		return false;
	}


	/**
	 * Add a parameter to this type
	 * @param  string $name    Attribute name
	 * @param  string $value   Attribute value
	 * @param  string $comment Comment for this parameter
	 * @return void
	 */
	function addParameter($name, $value, $comment = false){
		$tmp = new MIME_Type_Parameter;
		$tmp->name = $name;
		$tmp->value = $value;
		$tmp->comment = $comment;
		$this->parameters[$name] = $tmp;
	}


	/**
	 * Remove a parameter from this type
	 * @param  string $name Parameter name
	 * @return void
	 */
	function removeParameter($name){
		unset($this->parameters[$name]);
	}


	/**
	 * Autodetect a file's MIME-type
	 * This function may be called staticly.
	 * @param  string $file   Path to the file to get the type of
	 * @param  bool   $params Append MIME parameters if true
	 * @return string $file's MIME-type on success, PEAR_Error otherwise
	 * @since 1.0.0beta1
	 * @static
	 */
	public static function autoDetect($file, $params = false){
		@include_once 'System/Command.php';
		if(function_exists('mime_content_type')){
			$type = mime_content_type($file);
		} else
			if(class_exists('System_Command')){
				$type = MIME_Type::_fileAutoDetect($file);
			} else{
				return PEAR::raiseError("Sorry, can't autodetect; you need the mime_magic extension or System_Command and 'file' installed to use this function.");
			}

		// _fileAutoDetect() may have returned an error.
		if(PEAR::isError($type)){
			return $type;
		}

		// Don't return an empty string
		if(!$type || !strlen($type)){
			return PEAR::raiseError("Sorry, couldn't determine file type.");
		}

		// Strip parameters if present & requested
		if(MIME_Type::hasParameters($type) && !$params){
			$type = MIME_Type::stripParameters($type);
		}

		return $type;
	}

	/**
	 * Autodetect a file's MIME-type with 'file' and System_Command
	 * This function may be called staticly.
	 * @param  string $file   Path to the file to get the type of
	 * @return string $file's MIME-type
	 * @since 1.0.0beta1
	 * @static
	 */
	function _fileAutoDetect($file){
		// Sanity checks
		if(!file_exists($file)){
			return PEAR::raiseError("File \"$file\" doesn't exist");
		}

		if(!is_readable($file)){
			return PEAR::raiseError("File \"$file\" is not readable");
		}

		$cmd = new System_Command;


		// Make sure we have the 'file' command.
		$fileCmd = PEAR::getStaticProperty('MIME_Type', 'fileCmd');
		if(!$cmd->which($fileCmd)){
			unset($cmd);
			return PEAR::raiseError("Can't find file command \"{$fileCmd}\"");
		}

		$cmd->pushCommand($fileCmd, "-bi '{$file}'");
		$res = $cmd->execute();
		unset($cmd);

		return $res;
	}
}
